package com.vita.core1;

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.CompletableFuture;

public class Elevator {
    private int id;
    /**
     * 运行状态：0静止、1向上、-1向下
     */
    private int state = 0;

    /**
     * 当前所在楼层
     */
    private int nowFloor = 1;

    /**
     * 本电梯需要到达的
     */
    private Queue<Integer> list = new LinkedList<>();
    private Schedul schedul;

    public Elevator(int id) {
        this.id = id;
    }

    public void init(Schedul schedul) {
        this.state = 0;
        list.clear();
        this.schedul = schedul;
//        int number = new Random().nextInt(10) + 1;
//        this.list.add(3);
//        this.list.add(number);
    }

    /**
     * 根据当前所在楼层
     * 获取三个表list、up、dw中最近距离的楼层
     * 并开始运行
     */
    public void upOrDw() throws InterruptedException {
        /**
         * 1、获取目标
         * 2、确定上行（或下行、静止)
         * 3、开始上行（或下行）
         * 4、上行一楼，检查是否需要开门（需要开门就清除该层上行列表或本机列表中的本层）
         * 5、检查是否需要接着上行，需要接着上行-》3
         */






        // 根据三个表确定运行方向
        this.state = Helper.checkState(this.schedul, this.nowFloor, this.list);
        if (this.state == 1) {
            if (this.list.isEmpty() && this.schedul.getUpList().isEmpty() && this.schedul.getDwList().isEmpty()) {
                this.state = 0;
                return;
            }
            // 上行
            elevatUp();
            // 检查本层是否开门
            if (openTheDoor(this.list)) {
                // 检查本机器列表
                this.schedul.remove(this.schedul.getUpList(), this.nowFloor);
            } else if (openTheDoor(this.schedul.getUpList())) {
                // 检查上行列表
            }
        } else if (this.state == -1) {
            if (this.list.isEmpty() && this.schedul.getUpList().isEmpty() && this.schedul.getDwList().isEmpty()) {
                this.state = 0;
                return;
            }
            // 下行
            elevatDw();
            if (openTheDoor(this.list)) {
                this.schedul.remove(this.schedul.getDwList(), this.nowFloor);
            } else if (openTheDoor(this.schedul.getDwList())) {
            }
        }else {
            System.out.println("失去目标，静止");
        }
        if (this.list.isEmpty() && this.schedul.getUpList().isEmpty() && this.schedul.getDwList().isEmpty()) {
            this.state = 0;
            return;
        }
        Thread.sleep(1000);
        upOrDw();
    }

    public CompletableFuture<Integer> run() {
        return CompletableFuture.supplyAsync(() -> {
            System.out.println("电梯 " + id + " 号，启动-------------");
            try {
                upOrDw();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 1;
        });
    }

    // 获取最小距离并往列表里面添加
    private void addFloor(Queue<Integer> old, Queue<Integer> news) throws InterruptedException {
        if (!old.isEmpty()) {
            int floor = getNearFloor(old);
            if (floor != this.nowFloor) {
                news.add(floor);
            }
        }
    }

    // 获取最小绝对值对应的楼层（获取离电梯要到的最近的楼层），只在静止时调用
    public int getNearFloor(Queue<Integer> is) throws InterruptedException {
        int su = this.nowFloor;
        int value = 0;
        for (int xu : is) {
            if (su == xu) {
                if (this.state == 0) {
                    openTheDoor(is);
                }
            }

        }
        for (int xu : is) {
            // 求绝对值
            int newValue = Math.abs(xu - su);
            // 获得最小的绝对值和对应的楼层
            if (value == 0 || newValue < value) {
                value = newValue;
                su = xu;
            }
        }
        return su;
    }

    private boolean haveNext() {
        // list中没有符合的就清空
        if (haveNextInlist(this.list)) {
            return true;
        } else {
            this.list.clear();
        }

        if (this.state == 1) {
            // 向上，判断this.schedul.getUpList()
            if (haveNextInlist(this.schedul.getUpList())) {
                return true;
            }
        } else if (this.state == -1) {
            // 向下，判断this.schedul.getDwList()
            if (haveNextInlist(this.schedul.getDwList())) {
                return true;
            }
        }
        return false;
    }

    private boolean haveNextInlist(Queue<Integer> list) {
        if (!list.isEmpty()) {
            for (int i : list) {

                if (this.state == 1) {
                    // 上升，有大的数，true
                    if (this.nowFloor < i) {
                        return true;
                    }
                } else if (this.state == -1) {
                    // 下降，有小的数，true
                    if (this.nowFloor > i) {
                        return true;
                    }
                } else {
                    // 静止，有数，true
                    return true;
                }
            }
        }
        // 空。false
        return false;
    }

    /**
     * 返回本层是否已经开门
     */
    private boolean openTheDoor(Queue<Integer> list) throws InterruptedException {
        boolean isOpen = this.schedul.remove(list, this.nowFloor);
        if (isOpen) {
            System.out.println("电梯 " + this.id + " 号，" + this.nowFloor + "层，开门------");
        }
        return isOpen;
    }


    private void elevatUp() {
        this.nowFloor = this.nowFloor + 1;
        System.out.println("电梯 " + this.id + " 号，" + this.nowFloor + "层，上行");
    }

    private void elevatDw() {
        this.nowFloor = this.nowFloor - 1;
        System.out.println("电梯 " + this.id + " 号，" + this.nowFloor + "层，下行");
    }


    public int getNowFloor() {
        return nowFloor;
    }

    public void setNowFloor(int nowFloor) {
        this.nowFloor = nowFloor;
    }

    public int getState() {
        return state;
    }

    public void setState(int state) {
        this.state = state;
    }
}
